package elitech.vietnam.weatherfashion.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RelativeLayout;

/**
 * 
 * This view will auto determine the width or height by determining if the 
 * height or width is set and scale the other dimension depending on the images dimension
 * 
 * This view also contains an ImageChangeListener which calls changed(boolean isEmpty) once a 
 * change has been made to the ImageView
 * 
 * @author Maurycy Wojtowicz
 *
 */
public class ScaleImageView extends ImageView {
	private ImageChangeListener imageChangeListener;
	private boolean scaleToWidth = false; // this flag determines if should measure height manually dependent of width

	public ScaleImageView(Context context) {
		super(context);
		init();
	}

	public ScaleImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public ScaleImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init(){
		this.setScaleType(ScaleType.CENTER_INSIDE);
	}

	@Override
	public void setImageBitmap(Bitmap bm) {
		super.setImageBitmap(bm);
		if (imageChangeListener != null)
			imageChangeListener.changed((bm == null));
	}

	@Override
	public void setImageDrawable(Drawable d) {
		super.setImageDrawable(d);
		if (imageChangeListener != null)
			imageChangeListener.changed((d == null));
	}

	@Override
	public void setImageResource(int id){
		super.setImageResource(id);
	}

	public interface ImageChangeListener {
		// a callback for when a change has been made to this imageView
		void changed(boolean isEmpty); 
	}

	public ImageChangeListener getImageChangeListener() {
		return imageChangeListener;
	}

	public void setImageChangeListener(ImageChangeListener imageChangeListener) {
		this.imageChangeListener = imageChangeListener;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int width = MeasureSpec.getSize(widthMeasureSpec);
		int height = MeasureSpec.getSize(heightMeasureSpec);
		
		/**
		 * if both width and height are set scale width first. modify in future if necessary
		 */
		
		if(widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST){
			scaleToWidth = true;
		}else if(heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST){
			scaleToWidth = false;
		}else throw new IllegalStateException("width or height needs to be set to match_parent or a specific dimension");
		
		if(getDrawable()==null || getDrawable().getIntrinsicWidth()==0 ){
			// nothing to measure
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
			return;
		}else{
			if(scaleToWidth){
				int iw = this.getDrawable().getIntrinsicWidth();
				int ih = this.getDrawable().getIntrinsicHeight();
				int heightC = width*ih/iw;
				if(height > 0)
				if(heightC>height){
					// dont let hegiht be greater then set max
					heightC = height;
					width = heightC*iw/ih;
				}
				
				this.setScaleType(ScaleType.CENTER_CROP);
				setMeasuredDimension(width, heightC);
				
			}else{
				// need to scale to height instead
				int marg = 0;
				if(getParent()!=null){
					if(getParent().getParent()!=null){
						marg+= ((RelativeLayout) getParent().getParent()).getPaddingTop();
						marg+= ((RelativeLayout) getParent().getParent()).getPaddingBottom();
					}
				}
				
				int iw = this.getDrawable().getIntrinsicWidth();
				int ih = this.getDrawable().getIntrinsicHeight();

				width = height*iw/ih;
				height-=marg;
				setMeasuredDimension(width, height);
			}

		}
	}

}

////
//public class ScaleImageViewTouch extends ImageView implements OnTouchListener {
//    private Context mContext;
//    private float MAX_SCALE = 2f;
//
//    private Matrix mMatrix;
//    private final float[] mMatrixValues = new float[9];
//
//    // display width height.
//    private int mWidth;
//    private int mHeight;
//
//    private int mIntrinsicWidth;
//    private int mIntrinsicHeight;
//
//    private float mScale;
//    private float mMinScale;
//
//    private float mPrevDistance;
//    private boolean isScaling;
//
//    private int mPrevMoveX;
//    private int mPrevMoveY;
//    private GestureDetector mDetector;
//
//    String TAG = "ScaleImageView";
//
//    public ScaleImageViewTouch(Context context, AttributeSet attr) {
//        super(context, attr);
//        this.mContext = context;
//        initialize();
//    }
//
//    public ScaleImageViewTouch(Context context) {
//        super(context);
//        this.mContext = context;
//        initialize();
//    }
//
//    @Override
//    public void setImageBitmap(Bitmap bm) {
//        super.setImageBitmap(bm);
//        this.initialize();
//    }
//
//    @Override
//    public void setImageResource(int resId) {
//        super.setImageResource(resId);
//        this.initialize();
//    }
//
//    private void initialize() {
//        this.setScaleType(ScaleType.MATRIX);
//        this.mMatrix = new Matrix();
//        Drawable d = getDrawable();
//        if (d != null) {
//            mIntrinsicWidth = d.getIntrinsicWidth();
//            mIntrinsicHeight = d.getIntrinsicHeight();
//            setOnTouchListener(this);
//        }
//        mDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
//            @Override
//            public boolean onDoubleTap(MotionEvent e) {
//                maxZoomTo((int) e.getX(), (int) e.getY());
//                cutting();
//                return super.onDoubleTap(e);
//            }
//        });
//
//    }
//
//    @Override
//    protected boolean setFrame(int l, int t, int r, int b) {
//        mWidth = r - l;
//        mHeight = b - t;
//
//        mMatrix.reset();
//        int r_norm = r - l;
//        mScale = (float) r_norm / (float) mIntrinsicWidth;
//
//        int paddingHeight = 0;
//        int paddingWidth = 0;
//        // scaling vertical
//        if (mScale * mIntrinsicHeight > mHeight) {
//            mScale = (float) mHeight / (float) mIntrinsicHeight;
//            mMatrix.postScale(mScale, mScale);
//            paddingWidth = (r - mWidth) / 2;
//            paddingHeight = 0;
//            // scaling horizontal
//        } else {
//            mMatrix.postScale(mScale, mScale);
//            paddingHeight = (b - mHeight) / 2;
//            paddingWidth = 0;
//        }
//        mMatrix.postTranslate(paddingWidth, paddingHeight);
//
//        setImageMatrix(mMatrix);
//        mMinScale = mScale;
//        zoomTo(mScale, mWidth / 2, mHeight / 2);
//        cutting();
//        return super.setFrame(l, t, r, b);
//    }
//
//    protected float getValue(Matrix matrix, int whichValue) {
//        matrix.getValues(mMatrixValues);
//        return mMatrixValues[whichValue];
//    }
//
//    protected float getScale() {
//        return getValue(mMatrix, Matrix.MSCALE_X);
//    }
//
//    public float getTranslateX() {
//        return getValue(mMatrix, Matrix.MTRANS_X);
//    }
//
//    protected float getTranslateY() {
//        return getValue(mMatrix, Matrix.MTRANS_Y);
//    }
//
//    protected void maxZoomTo(int x, int y) {
//        if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) {
//            // threshold 0.1f
//            float scale = mMinScale / getScale();
//            zoomTo(scale, x, y);
//        } else {
//            float scale = MAX_SCALE / getScale();
//            zoomTo(scale, x, y);
//        }
//    }
//
//    public void zoomTo(float scale, int x, int y) {
//        if (getScale() * scale < mMinScale) {
//            return;
//        }
//        if (scale >= 1 && getScale() * scale > MAX_SCALE) {
//            return;
//        }
//        mMatrix.postScale(scale, scale);
//        // move to center
//        mMatrix.postTranslate(-(mWidth * scale - mWidth) / 2, -(mHeight * scale - mHeight) / 2);
//
//        // move x and y distance
//        mMatrix.postTranslate(-(x - (mWidth / 2)) * scale, 0);
//        mMatrix.postTranslate(0, -(y - (mHeight / 2)) * scale);
//        setImageMatrix(mMatrix);
//    }
//
//    public void cutting() {
//        int width = (int) (mIntrinsicWidth * getScale());
//        int height = (int) (mIntrinsicHeight * getScale());
//        if (getTranslateX() < -(width - mWidth)) {
//            mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0);
//        }
//        if (getTranslateX() > 0) {
//            mMatrix.postTranslate(-getTranslateX(), 0);
//        }
//        if (getTranslateY() < -(height - mHeight)) {
//            mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight));
//        }
//        if (getTranslateY() > 0) {
//            mMatrix.postTranslate(0, -getTranslateY());
//        }
//        if (width < mWidth) {
//            mMatrix.postTranslate((mWidth - width) / 2, 0);
//        }
//        if (height < mHeight) {
//            mMatrix.postTranslate(0, (mHeight - height) / 2);
//        }
//        setImageMatrix(mMatrix);
//    }
//
//    private float distance(float x0, float x1, float y0, float y1) {
//        float x = x0 - x1;
//        float y = y0 - y1;
//        return FloatMath.sqrt(x * x + y * y);
//    }
//
//    private float dispDistance() {
//        return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight);
//    }
//
//    @Override
//    public boolean onTouchEvent(MotionEvent event) {
//        if (mDetector.onTouchEvent(event)) {
//            return true;
//        }
//        int touchCount = event.getPointerCount();
//        switch (event.getAction()) {
//        case MotionEvent.ACTION_DOWN:
//        case MotionEvent.ACTION_POINTER_1_DOWN:
//        case MotionEvent.ACTION_POINTER_2_DOWN:
//            if (touchCount >= 2) {
//                float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
//                mPrevDistance = distance;
//                isScaling = true;
//            } else {
//                mPrevMoveX = (int) event.getX();
//                mPrevMoveY = (int) event.getY();
//            }
//        case MotionEvent.ACTION_MOVE:
//            if (touchCount >= 2 && isScaling) {
//                float dist = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
//                float scale = (dist - mPrevDistance) / dispDistance();
//                mPrevDistance = dist;
//                scale += 1;
//                scale = scale * scale;
//                zoomTo(scale, mWidth / 2, mHeight / 2);
//                cutting();
//            } else if (!isScaling) {
//                int distanceX = mPrevMoveX - (int) event.getX();
//                int distanceY = mPrevMoveY - (int) event.getY();
//                mPrevMoveX = (int) event.getX();
//                mPrevMoveY = (int) event.getY();
//                mMatrix.postTranslate(-distanceX, -distanceY);
//                cutting();
//            }
//            break;
//        case MotionEvent.ACTION_UP:
//        case MotionEvent.ACTION_POINTER_UP:
//        case MotionEvent.ACTION_POINTER_2_UP:
//            if (event.getPointerCount() <= 1) {
//                isScaling = false;
//            }
//            break;
//        }
//        return true;
//    }
//
//    @Override
//    public boolean onTouch(View v, MotionEvent event) {
//        return super.onTouchEvent(event);
//    }

//}